package com.hzqy.web.ac;

import com.alibaba.fastjson.JSONObject;
import com.hzqy.commons.utils.SystemConfigUtils;
import com.hzqy.commons.utils.WChatPayUtil;
import com.hzqy.service.wchat.WchatScanPayService;
import com.hzqy.web.vo.SysProductVo;
import com.hzqy.web.vo.WchatOrderResultVo;
import com.hzqy.web.vo.WchatPaymentVo;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;


/**
 * 
 * <p>微信支付文档链接: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_1。<br>
 * <br>
 * <h3>微信扫码支付流程: </h3><br>
 *   1. 获取支付链接， 生成产品二维码， 支付链接见 getPayUrl(product_id); product_id为商户自定义产品id。 生成二维码见getPayQrcode(url, logopath);<br>
 *   2. 用户扫码后， 微信回调商户平台， 开始微信支付流程。 <br>
 *   <blockquote>  2.1 回调地址配置在微信公众平台 见 https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_3。<br>
 *     2.2 回调  prePay(); 需要返回预订单id返回微信，参数中带有二维码中的产品product_id， 返回后开始用户支付流程。<br>
 *     2.3 prePay();方法中调用unifiedOrder(product_id, openid, is_subscribe); 需要告知微信本次支付信息(价格，名称，币种，服务器ip， <b>支付回调路径</b>等等)，返回预订单id。</blockquote><br>
 *   3. 用户支付完成后，按订单种的支付回调路径回调payResult(); 接收结果。完成支付流程。<br>
 * </p>
 * @author zyf
 * 
 */
@Controller
@RequestMapping("/third_wechat_payment")
public class WchatScanPayAction {
	
	protected final Logger LOG = LoggerFactory.getLogger(getClass());
	
	@Autowired
	private WchatScanPayService wchatScanPayService;


	/**
	 * 扫码支付，预创建订单
	 *
	 * 参数 payinfo =
	 * {
	 *     serverid: 0571000199,
	 *     pay_money: 5.00,
	 * }
	 *
	 */
	@CrossOrigin(origins = "*",maxAge = 3000)
	@GetMapping(value = "/wchatpayCreateOrder")
	@ResponseBody
	public Object wchatpayCreateOrder(WchatPaymentVo payment){
		long t1 = System.currentTimeMillis();
		LOG.debug("(" + t1 + ")微信支付 进入支付平台参数: " + payment);
		Map<String, Object> resultMap = wchatScanPayService.wchatpayCreateOrder(payment);
		LOG.debug("(" + t1 + ")微信支付 进入支付平台返回: " + resultMap + " 耗时:" + (System.currentTimeMillis() - t1) + "ms");
		return resultMap;
	}




	/**
	 * 扫描二维码后回调
	 * 	生成预订单prepay_id并返回
	 * 	等待用户支付
	 */
	@RequestMapping(value = "/prePay")
	public void prePay(HttpServletRequest request, HttpServletResponse response){
		long t1 = System.currentTimeMillis();
		try {
			request.setCharacterEncoding("UTF-8");
			response.setContentType("text/xml;charset=UTF-8");
			String xml = WChatPayUtil.getStringFromInputStream(request.getInputStream());
			LOG.debug("(" + t1 + ")微信支付 扫码回调接口参数: " + xml);
			String result = wchatScanPayService.prePay(xml);
			LOG.debug("(" + t1 + ")微信支付 扫码回调接口返回: " + result + " 耗时:" + (System.currentTimeMillis() - t1) + "ms");
			WChatPayUtil.printToWriter(response.getWriter(), result);
		} catch (IOException e) {
			LOG.error("IOException", e);
		}
	}
	
	/**
	 * 统一下单API 获取订单prepay_id
	 */
	@ResponseBody
	@RequestMapping(value = "/unifiedOrder", method = RequestMethod.POST)
	public Map<String, Object> unifiedOrder(
			@RequestParam(value = "product_id") String product_id, 
			@RequestParam(value = "openid") String openid,
			@RequestParam(value = "is_subscribe") String is_subscribe){
		long t1 = System.currentTimeMillis();
		LOG.debug("(" + t1 + ")微信支付 统一下单接口参数: product_id=" + product_id + "openid=" + openid + "is_subscribe=" + is_subscribe);
		Map<String, Object> returnMap = wchatScanPayService.unifiedOrder(product_id, openid, is_subscribe);
		LOG.debug("(" + t1 + ")微信支付 统一下单接口返回: " + returnMap + "(JSON) 耗时:" + (System.currentTimeMillis() - t1) + "ms");
		return returnMap;
	}
	/**
	 * 异步回调 接收支付结果
	 * 	需要返回信息告知微信已经成功接收结果, 否则微信会重复请求
	 */
	@RequestMapping(value = "/payResult", method = RequestMethod.POST)
	public void payResult(HttpServletRequest request, HttpServletResponse response){
		long t1 = System.currentTimeMillis();
		try {
			request.setCharacterEncoding("UTF-8");
			response.setContentType("text/xml;charset=UTF-8");
			String xml = WChatPayUtil.getStringFromInputStream(request.getInputStream());
			LOG.debug("(" + t1 + ")微信支付 支付结果回调接口参数: " + xml);
			String result = wchatScanPayService.payResult(xml);
			LOG.debug("(" + t1 + ")微信支付 支付结果回调接口返回: " + result + " 耗时:" + (System.currentTimeMillis() - t1) + "ms");
			WChatPayUtil.printToWriter(response.getWriter(), result);
		} catch (IOException e) {
			LOG.error("IOException", e);
		}
	}
	
	/**
	 * 获取下单链接 返回长/短两种链接
	 */
	@ResponseBody
	@RequestMapping(value = "/getPayUrl", method = RequestMethod.GET)
	public Map<String, Object> getPayUrl(@RequestParam(value = "product_id") String product_id){
		long t1 = System.currentTimeMillis();
		LOG.debug("(" + t1 + ")微信支付 获取长/短支付链接接口参数: product_id=" + product_id);
		Map<String, Object> returnMap = wchatScanPayService.getPayUrl(product_id);
		LOG.debug("(" + t1 + ")微信支付 获取长/短支付链接接口返回: " + returnMap + "(JSON) 耗时:" + (System.currentTimeMillis() - t1) + "ms");
		return returnMap;
	}
	
	/**
	 * 查询订单API
	 */
	@ResponseBody
	@RequestMapping(value = "/queryOrder", method = RequestMethod.GET)
	public WchatOrderResultVo queryOrder(
			@RequestParam(value = "out_trade_no", required = false) String out_trade_no,
			@RequestParam(value = "transaction_id", required = false) String transaction_id){
		return wchatScanPayService.queryOrder(out_trade_no, transaction_id);
	}
	
	/**
	 * 关闭订单API
	 */
	@ResponseBody
	@RequestMapping(value = "/closeOrder", method = RequestMethod.GET)
	public WchatOrderResultVo closeOrder(@RequestParam(value = "out_trade_no") String out_trade_no){
		return wchatScanPayService.closeOrder(out_trade_no);
	}
	
	/**
	 * 退款查询API
	 */
	@ResponseBody
	@RequestMapping(value = "/refundQuery", method = RequestMethod.GET)
	public WchatOrderResultVo refundQuery(
			@RequestParam(value = "out_trade_no", required = false) String out_trade_no, 
			@RequestParam(value = "transaction_id", required = false) String transaction_id, 
			@RequestParam(value = "out_refund_no", required = false) String out_refund_no, 
			@RequestParam(value = "refund_id", required = false) String refund_id){
		return wchatScanPayService.refundQuery(out_trade_no, transaction_id, out_refund_no, refund_id);
	}
	
	/**
	 * 查询产品
	 */
	@ResponseBody
	@RequestMapping(value = "/getProduct", method = RequestMethod.GET)
	public SysProductVo getProduct(@RequestParam(value = "product_id") String product_id) {
		return wchatScanPayService.getProduct(product_id);
	}
	
	/**
	 * 鉴权
	 */
	@RequestMapping(value = "/authinfo")
	public void authinfo(HttpServletRequest request, HttpServletResponse response) {
		long t1 = System.currentTimeMillis();
		try {
			String json = request.getParameter("authinfo");
			LOG.debug("(" + t1 + ")微信支付 鉴权接口参数: " + json);
			String result = wchatScanPayService.authinfo(json);
			LOG.debug("(" + t1 + ")微信支付 鉴权接口返回: " + result + " 耗时:" + (System.currentTimeMillis() - t1) + "ms");
			WChatPayUtil.printToWriter(response.getWriter(), result);
		} catch (IOException e) {
			LOG.error("IOException", e);
		}
	}
	
	/**
	 * bss 订购/退订
	 * @param serverid 业务账号
	 * @param trade_no 订单号
	 * @param transaction_id 流水号
	 * @param productcode 产品编号
	 * @param order 订购/退订 true/false
	 * @return Map: (success:true/false,msg:xxxx)
	 */
	@ResponseBody
	@RequestMapping(value = "/bssOrder")
	public Map<String, String> bssOrder(String serverid, String trade_no, String transaction_id, String productcode, boolean order,
			HttpServletRequest request) {
		long t1 = System.currentTimeMillis();
		Map<String, String> resultMap = new HashMap<String, String>();
		try {
			LOG.debug("(" + t1 + ")BSS订购/退订接口参数: " + serverid + " " + trade_no + " " + transaction_id + " " + productcode + " " + order);
			resultMap = wchatScanPayService.bssOrder(serverid, trade_no, transaction_id, productcode, order);
			LOG.debug("(" + t1 + ")BSS订购/退订接口返回: " + resultMap + " 耗时:" + (System.currentTimeMillis() - t1) + "ms");
		} catch (Exception e) {
			resultMap.put("success", "false");
			//resultMap.put("msg", e.getMessage());
			LOG.error("IOException", e);
		}
		return resultMap;
	}
	
	/**
	 * bss 鉴权
	 * @param serverid 业务账号
	 * @param productcode 产品编号
	 * @return Map: (success:true/false,msg:xxxx)
	 */
	@ResponseBody
	@RequestMapping(value = "/bssOrderQuery")
	public Map<String, String> bssOrderQuery(String serverid, String productcode,
			HttpServletRequest request) {
		long t1 = System.currentTimeMillis();
		Map<String, String> resultMap = new HashMap<String, String>();
		try {
			LOG.debug("(" + t1 + ")BSS鉴权接口参数: " + serverid + " " + productcode + " ");
			resultMap = wchatScanPayService.bssOrderQuery(serverid, productcode);
			LOG.debug("(" + t1 + ")BSS鉴权接口返回: " + resultMap + " 耗时:" + (System.currentTimeMillis() - t1) + "ms");
		} catch (Exception e) {
			resultMap.put("success", "false");
			//resultMap.put("msg", e.getMessage());
			LOG.error("IOException", e);
		}
		return resultMap;
	}
	
	
	/**
	 * 模拟登录demo.jsp中使用
	 */
	@RequestMapping(value = "/login")
	public String login(
			HttpSession session,
			@RequestParam(value = "serverid") String serverid,
			@RequestParam(value = "product_id") String product_id,
			@RequestParam(value = "resolution") String resolution,
			@RequestParam(value = "source") String source,
			@RequestParam(value = "back_url") String back_url,
			@RequestParam(value = "notify_url") String notify_url) {
		try {
			Map<String, Object> map = new TreeMap<String, Object>();
			map.put("paytype", "wxscanpay");
			map.put("serverid", serverid);
			map.put("resolution", resolution);
			map.put("product_id", product_id);
			map.put("back_url", back_url);
			map.put("notify_url", notify_url);
			map.put("group", "ZJTELECOMHotel");
			map.put("trade_no", WChatPayUtil.createOrderId());
			map.put("source", source);
			map.put("timestamp", String.valueOf(System.currentTimeMillis()));
			map.put("sign", WChatPayUtil.sign(map, SystemConfigUtils.getSysConfig("secret.secretcode." + source)));
			String params = JSONObject.toJSONString(map);
			String payinfo = "wchatpayLogin.do?payinfo=" + URLEncoder.encode(params, "UTF-8");
			return "redirect:" + payinfo;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "redirect:../commons/error.jsp";
	}
	
	
}
